#ifndef PLAYER_H
#define PLAYER_H

#include "Interface.h"

//===========================================================================
// Move
//===========================================================================
struct Move
{
    enum ECourse {
        NONE,
        LEFT,
        RIGHT,
    };
    
    Position position;
    ECourse  course;

    Move( void )
        : course( NONE )
    {}        
    
    Move(
        const Move & move
    )   : position( move.position )
        , course(   move.course   )
    {}

    bool Parse(
        char course
    );
    
    bool Parse(
        const char * command
    );
};

//===========================================================================
// Player
//===========================================================================
class Player : public IPlayer
{
public :

    Player(
        IBoard * board,
        Piece    type,
        ESide    side
    );
    virtual ~Player( void );

public : // IPlayer implementation    
    
    virtual bool OnTurn( void ) = 0;

    virtual void Release( void ) = 0;

    inline Piece GetPieceType( void ) const;

    inline ESide GetSide( void ) const;

protected :

    bool GenerateMove(
        const IRoute *      route,
              Move::ECourse course,
              IRoute *      appended = NULL
    );
    
    inline int GetCourse(
        Move::ECourse course
    ) const;

    IBoard * m_board;
    Piece    m_piece;
    ESide    m_side;
    
    int      m_forward;
    int      m_left;
    int      m_right;
};

//===========================================================================
// HumanPlayer
//===========================================================================
class HumanPlayer : public Player
{
public :

    HumanPlayer(
        IBoard * board,
        Piece    type,
        ESide    side
    );
    virtual ~HumanPlayer( void );

public : // IPlayer implementation    

    void Release( void );

private :

    static void Release( HumanPlayer * player );

    void GetUserMove(
        Move & move,
        bool & abandon
    );

protected : // IPlayer implementation    

    bool OnTurn( void );
};

//===========================================================================
// AiPlayer
//===========================================================================
class AiPlayer : public Player
{
public :

    AiPlayer(
        IBoard * board,
        Piece    type,
        ESide    side
    );

    virtual ~AiPlayer( void );

public : // IPlayer implementation    
    
    void Release( void );

private :

    static void Release( AiPlayer * player );

    unsigned int FindAllDeepestRoutes(
        vector< IRoute * > & routes
    );

    void FindAllDeepestRoutes(
        IRoute *             route,
        vector< IRoute * > & routes,
        unsigned int &       maxmove,
        IRoute *             appended
    );

    void ClearRoutes(
        vector< IRoute * > & routes
    );

protected : // IPlayer implementation

    bool OnTurn( void );

};

#endif // PLAYER_H